home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 4 / The 640 Meg Shareware Studio CD-ROM Volume IV (Data Express)(1994).ISO / clang / xlib05.zip / XBEZIER.ASM < prev    next >
Assembly Source File  |  1993-08-25  |  14KB  |  676 lines

  1.  
  2. ;-----------------------------------------------------------------------
  3. ; MODULE XBEZIER
  4. ;
  5. ;
  6. ; Compile with TASM.
  7. ; C near-callable.
  8. ;
  9. ; This module was written by Matthew MacKenzie
  10. ; matm@eng.umd.edu
  11. ;-----------------------------------------------------------------------
  12. include xlib.inc
  13. include xbezier.inc
  14.  
  15.  
  16. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  17. ; _x_bezier
  18. ;
  19. ; Plot a Bezier curve, which is described by a box of two endpoints
  20. ; and two control points:
  21. ;                           C1--------C2
  22. ;                           /           \
  23. ;                          /             \
  24. ;                        E1..............E2
  25. ;
  26. ; All coordinates must be in the range -1024 to 3071.
  27. ; No clipping is performed.
  28. ;
  29. ; C near-callable as:
  30. ; x_bezier (int E1x, int E1y, int C1x, int C1y, int C2x, int C2y,
  31. ;           int E2x, int E2y, int levels, char color,
  32. ;           unsigned int PageOffset);
  33. ;
  34. ; All four main registers are totaled.
  35. ; This function may use as many as 162 bytes of stack space.
  36.  
  37. ; Bezier curves need 32-bit precision, so we'll define macros and
  38. ; constants for operations on 32-bit virtual registers V0, V1, and V2.
  39. ; V0 is made up of DI and AX, V1 of SI and BX, and V2 of CX and DX.
  40.  
  41. LowWord         equ     0
  42. HighWord        equ     2
  43.  
  44. ; to load data --
  45.  
  46. LoadV0 macro loc, field
  47.     mov ax, word ptr [bp + loc + field + LowWord]
  48.     mov di, word ptr [bp + loc + field + HighWord]
  49.     endm
  50.  
  51. LoadV1 macro loc, field
  52.     mov bx, word ptr [bp + loc + field + LowWord]
  53.     mov si, word ptr [bp + loc + field + HighWord]
  54.     endm
  55.  
  56. LoadV2 macro loc, field
  57.     mov dx, word ptr [bp + loc + field + LowWord]
  58.     mov cx, word ptr [bp + loc + field + HighWord]
  59.     endm
  60.  
  61. ; to store data --
  62.  
  63. StoreV0 macro loc, field
  64.     mov word ptr [bp + loc + field + LowWord], ax
  65.     mov word ptr [bp + loc + field + HighWord], di
  66.     endm
  67.  
  68. StoreV1 macro loc, field
  69.     mov word ptr [bp + loc + field + LowWord], bx
  70.     mov word ptr [bp + loc + field + HighWord], si
  71.     endm
  72.  
  73.  
  74. ; to take the average of two registers (result is in first register) --
  75.  
  76. AverageV0nV1 macro
  77.     add ax, bx
  78.     adc di, si
  79.     shr di, 1
  80.     rcr ax, 1
  81.     endm
  82.  
  83. AverageV0nV2 macro
  84.     add ax, dx
  85.     adc di, cx
  86.     shr di, 1
  87.     rcr ax, 1
  88.     endm
  89.  
  90. AverageV1nV2 macro
  91.     add bx, dx
  92.     adc si, cx
  93.     shr si, 1
  94.     rcr bx, 1
  95.     endm
  96.  
  97.  
  98. ; to take the average of a register and data --
  99.  
  100. AverageV1nData macro loc, field
  101.     add bx, word ptr [bp + loc + field + LowWord]
  102.     adc si, word ptr [bp + loc + field + HighWord]
  103.     shr si, 1
  104.     rcr bx, 1
  105.     endm
  106.  
  107. AverageV2nData macro loc, field
  108.     add dx, word ptr [bp + loc + field + LowWord]
  109.     adc cx, word ptr [bp + loc + field + HighWord]
  110.     shr cx, 1
  111.     rcr dx, 1
  112.     endm
  113.  
  114.  
  115. ; to turn a 32-bit fixed point data into a regular integer --
  116.  
  117. Extract macro reg, source, field
  118.     mov reg, word ptr [bp + source + field + HighWord]
  119.     shr reg, 3
  120.     adc reg, 0          ; round
  121.     endm
  122.  
  123.  
  124. ; to turn an integer argument into a 32-bit fixed point number
  125. ; and store it as local data --
  126.  
  127. Convert macro source, dest, field
  128.     mov ax, source
  129.     add ax, 1024
  130.     shl ax, 3
  131.     push ax
  132.     push 0
  133.     endm
  134.  
  135.  
  136. ; useful numbers for dealing with Bezier boxes (sets of four points) --
  137.  
  138. XCoord      equ     4
  139. YCoord      equ     0
  140.  
  141. ; stack offsets for splitting boxes
  142. E1Src       equ     48
  143. C1Src       equ     40
  144. C2Src       equ     32
  145. E2Src       equ     24
  146.  
  147. E1Dest      equ     48
  148. P1Dest      equ     40
  149. P4Dest      equ     32
  150. P6Dest      equ     24
  151. P5Dest      equ     16
  152. P2Dest      equ     8
  153. E2Dest      equ     0
  154.  
  155. ; stack offsets for drawing boxes
  156. E1Draw      equ     24
  157. C1Draw      equ     16
  158. C2Draw      equ     8
  159. E2Draw      equ     0
  160.  
  161.     .data
  162.  
  163.     align 2
  164.  
  165. ; depth of recursion at which to plot
  166. WhenToDraw label byte
  167.    db 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
  168.    db 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5
  169.  
  170.  
  171. ; since we'll be moving bp and sp in our recursion,
  172. ; we need to put local storage in the data segment
  173. level           dw  (?)
  174. gencount        dw  (?)
  175. AdjustedOffs    dw  (?)
  176. p1xt            dw  (?)
  177. p1yt            dw  (?)
  178. p2xt            dw  (?)
  179. p2yt            dw  (?)
  180. p4xt            dw  (?)
  181. p4yt            dw  (?)
  182. p5xt            dw  (?)
  183. p5yt            dw  (?)
  184. c1xt            dw  (?)
  185. c1yt            dw  (?)
  186. c2xt            dw  (?)
  187. c2yt            dw  (?)
  188. xdiff           dw  (?)
  189. ydiff           dw  (?)
  190. moveline        dw  (?)
  191. stepper         dw  (?)
  192. bptemp          dw  (?)
  193.  
  194. ; by the same token we need a copy of this argument
  195. Colort          dw  (?)
  196.  
  197.  
  198. ColumnMasks label byte
  199.     db 011h, 022h, 044h, 088h
  200.  
  201.     .code
  202.  
  203.     align 2
  204. _x_bezier proc
  205. ARG     E1x, E1y, C1x, C1y, C2x, C2y, E2x, E2y, Levels, Color, PageOffs:word
  206.  
  207.     push bp
  208.     mov bp, sp          ; caller's stack frame
  209.     push si
  210.     push di
  211.     push es
  212.  
  213.     ; set local variables
  214.     mov ax, -1024       ; 1024 rows
  215.     imul [_ScrnLogicalByteWidth]
  216.     add ax, PageOffs
  217.     sub ax, 256         ; 1024 columns
  218.     mov AdjustedOffs, ax ; subtract 1024 rows and 1024 columns
  219.  
  220. ; copy color into data segment so we can change bp & sp
  221.     mov ax, Color
  222.     mov Colort, ax
  223.  
  224.     mov cx, Levels
  225.     dec cx              ; gencount (number of boxes we will actually plot) =
  226.     mov ax,1            ; 2^(Levels - 1)
  227.     shl ax,cl
  228.     dec ax
  229.     mov gencount, ax
  230.  
  231.     mov [level], 0      ; variable to tell us where we are in the stack
  232.     mov bptemp, bp        ; when the dust settles at the end
  233.  
  234. ; translate coordinates for adjusted offset, convert 'em to fixed-point
  235. ; with 13 bits for the integer part and 19 for the fractional part,
  236. ; and push them onto the stack in the right order to for a Bezier box
  237.  
  238.     Convert E2x
  239.     Convert E2y
  240.  
  241.     Convert C2x
  242.     Convert C2y
  243.  
  244.     Convert C1x
  245.     Convert C1y
  246.  
  247.     Convert E1x
  248.     Convert E1y
  249.  
  250.     mov bp, sp          ; we are using them as basically one pointer
  251.  
  252.     mov ax, 0a000h      ; point extra segment to VGA memory
  253.     mov es, ax
  254.  
  255.     mov dx, SC_INDEX
  256.     mov al, MAP_MASK
  257.     out dx, al
  258.  
  259. MainLoop:
  260.     mov si, gencount
  261.     mov ax, 0
  262.     mov al, WhenToDraw[si]
  263.     cmp ax, level       ; are we at a terminal curve?
  264.     jne Recurse
  265.     jmp PlotCurve
  266.  
  267. Recurse:
  268. ; not at a terminal -- so expand this curve into two more and recurse
  269.  
  270. ; start with:
  271. ;    C1___C2
  272. ;     |    |
  273. ;    E1...E2
  274. ;
  275. ; stack looks like:  E1 C1 C2 E2
  276.  
  277. ; expand like this:
  278. ;    C1.....P3.....C2
  279. ;     .   .     .   .
  280. ;     . _P4_P6__P5_ .
  281. ;    P1-   .. ..   P2
  282. ;     |  ..     ..  |
  283. ;     |..         ..|
  284. ;    E1............E2
  285. ;
  286. ; stack looks like:  E1 P1 P4 P6 P5 P2 E2
  287. ; Since P6 is part of both new boxes, we use it twice.
  288.  
  289.     sub sp, 24
  290.     sub bp, 24
  291.  
  292. ; new points for X --
  293.     LoadV0      E1Src, XCoord
  294.     LoadV1      E2Src, XCoord
  295.     StoreV1     E2Dest, XCoord
  296.     LoadV2      C1Src, XCoord
  297.     AverageV0nV2
  298.     StoreV0     P1Dest, XCoord
  299.     AverageV1nData C2Src, XCoord
  300.     StoreV1     P2Dest, XCoord
  301.     AverageV2nData C2Src, XCoord
  302.     AverageV0nV2
  303.     StoreV0     P4Dest, XCoord
  304.     AverageV1nV2
  305.     StoreV1     P5Dest, XCoord
  306.     AverageV0nV1
  307.     StoreV0     P6Dest, XCoord
  308.  
  309. ; same thing for Y --
  310.     LoadV0      E1Src, YCoord
  311.     LoadV1      E2Src, YCoord
  312.     StoreV1     E2Dest, YCoord
  313.     LoadV2      C1Src, YCoord
  314.     AverageV0nV2
  315.     StoreV0     P1Dest, YCoord
  316.     AverageV1nData C2Src, YCoord
  317.     StoreV1     P2Dest, YCoord
  318.     AverageV2nData C2Src, YCoord
  319.     AverageV0nV2
  320.     StoreV0     P4Dest, YCoord
  321.     AverageV1nV2
  322.     StoreV1     P5Dest, YCoord
  323.     AverageV0nV1
  324.     StoreV0     P6Dest, YCoord
  325.  
  326.     inc level           ; one level further into stack
  327.     jmp MainLoop
  328.  
  329. PlotCurve:
  330. ; pull 16-bit coordinates back out of 32-bit fixed-point coordinates;
  331. ; integer part is highest 13 bits
  332.  
  333.     Extract cx, C1Draw, XCoord
  334.     Extract di, E1Draw, XCoord
  335.     mov c1xt, cx
  336.     add cx, di
  337.     shr cx, 1
  338.     mov p1xt, cx
  339.  
  340.     Extract ax, C1Draw, YCoord
  341.     Extract si, E1Draw, YCoord
  342.     mov c1yt, ax
  343.     add ax, si
  344.     shr ax, 1
  345.     mov p1yt, ax
  346.     call ShortLine      ; line from P1 to E1
  347.  
  348.     Extract cx, E2Draw, XCoord
  349.     Extract di, C2Draw, XCoord
  350.     mov c2xt, di
  351.     add di, cx
  352.     shr di, 1
  353.     mov p2xt, di
  354.  
  355.     Extract ax, E2Draw, YCoord
  356.     Extract si, C2Draw, YCoord
  357.     mov c2yt, si
  358.     add si, ax
  359.     shr si, 1
  360.     mov p2yt, si
  361.     call ShortLine      ; line from E2 to P2
  362.  
  363. ; P3 is not in any line we draw, so we'll use it now to find both P5
  364. ; for the line after this on, and P4 for this line, then discard it --
  365.     mov bx, c1xt
  366.     add bx, c2xt
  367.     shr bx, 1
  368.     mov dx, c1yt
  369.     add dx, c2yt
  370.     shr dx, 1
  371.  
  372. ; find P5 x and save for later lines
  373.     mov cx, p2xt
  374.     add cx, bx
  375.     shr cx, 1
  376.     mov p5xt, cx
  377. ; find P4 x for this line
  378.     mov cx, p1xt
  379.     add cx, bx
  380.     shr cx, 1
  381.     mov p4xt, cx
  382.     mov di, p1xt
  383.  
  384. ; find P5 y and save for later lines
  385.     mov ax, p2yt
  386.     add ax, dx
  387.     shr ax, 1
  388.     mov p5yt, ax
  389. ; find P4 y for this line
  390.     mov ax, p1yt
  391.     add ax, dx
  392.     shr ax, 1
  393.     mov p4yt, ax
  394.     mov si, p1yt
  395.     call ShortLine      ; line from P4 to P1 -- finally!
  396.  
  397. ; we've already done all the work for these last two --
  398.     mov cx, p2xt
  399.     mov di, p5xt
  400.     mov ax, p2yt
  401.     mov si, p5yt
  402.     call ShortLine      ; line from P2 to P5
  403.  
  404.     mov cx, p5xt
  405.     mov di, p4xt
  406.     mov ax, p5yt
  407.     mov si, p4yt
  408.     call ShortLine      ; line from P5 to P4
  409.  
  410. ; we've drawn our five lines; this bezier box
  411. ; can be dropped off the stack
  412.     add bp, 24
  413.     add sp, 24
  414.  
  415.     dec gencount
  416.     mov cx, gencount
  417.     cmp cx, -1
  418.  
  419.     je WrapUp           ; if we've generated all the terminal nodes we
  420.                         ; are supposed to, we pack our bags and go.
  421.     dec level
  422.     jmp MainLoop
  423.  
  424. WrapUp:
  425. ; plot the final point, which is simply the original E1
  426.  
  427.     mov bp, bptemp      ; back where we started
  428.     mov ax, E1y
  429.     add ax, 1024
  430.     mul [_ScrnLogicalByteWidth]
  431.     mov di, E1x
  432.     add di, 1024
  433.     mov si, di
  434.     shr di, 2
  435.     add di, ax
  436.     add di, AdjustedOffs
  437.     and si, 3
  438.     mov al, ColumnMasks[si]
  439.     mov ah, byte ptr Color
  440.     mov dx, SC_INDEX + 1
  441.     out dx, al
  442.     mov es:[di], ah
  443.  
  444.     pop es
  445.     pop di
  446.     pop si
  447.     mov sp, bp
  448.     pop bp
  449.     ret                 ; git
  450.  
  451. ; ShortLine subfunction --
  452. ;
  453. ; This is designed for short line segments.  For longer lines,
  454. ; especially horizontal ones, the x_line routine in the XLINE module
  455. ; would be faster.  But calling that from here it would be a lot of
  456. ; extra complication.  This is part of the x_bezier routine because
  457. ; it has no particular outside use, and we can call it much faster
  458. ; through registers than through the stack.
  459. ;
  460. ; Since our line segments overlap, the second endpoint is not drawn.
  461. ; These routines are all out of order for the sake of conditional jumps.
  462.  
  463. LRHorz:
  464.     dec di
  465. LRHorzLoop:
  466.     rol al, 1
  467.     adc bx, 0
  468.     out dx, al
  469.     mov es:[bx], ah
  470.     sub di, 1
  471.     jg LRHorzLoop
  472.     retn
  473.  
  474. ; You are in a maze of little subroutines, all alike...
  475.  
  476.  
  477. LR45Deg:
  478.     dec si
  479. LR45DegLoop:
  480.     add bx, cx
  481.     rol al, 1
  482.     adc bx, 0
  483.     out dx, al
  484.     mov es:[bx], ah
  485.     sub si, 1
  486.     jg LR45DegLoop
  487.     retn
  488.  
  489.  
  490. LRXMajor:
  491.     mov cx, di
  492.     dec cx
  493.     shr di, 1
  494. LRXMajorLoop:
  495.     sub di, si
  496.     jge LRXMajorIterate
  497.     add di, xdiff
  498.     add bx, moveline
  499. LRXMajorIterate:
  500.     rol al, 1
  501.     adc bx, 0
  502.     out dx, al
  503.     mov es:[bx], ah
  504.     sub cx, 1
  505.     jg LRXMajorLoop
  506.     retn
  507.  
  508.  
  509. LeftToRight:
  510.     mov xdiff, di       ; store distance across line
  511.  
  512.     mov cx, [_ScrnLogicalByteWidth]
  513.     cmp si, 0           ; check if height is positive, negative, or zero
  514.     je LRHorz
  515.     jg LRTopToBottom
  516.     neg si
  517.     neg cx
  518. LRTopToBottom:
  519.     mov ydiff, si
  520.     mov moveline, cx
  521.     cmp di, si
  522.     jg LRXMajor
  523.     je LR45Deg
  524.  
  525.  
  526. LRYMajor:
  527.     mov cx, si
  528.     dec cx
  529.     shr si, 1
  530. LRYMajorLoop:
  531.     add bx, moveline
  532.     sub si, di
  533.     jge LRYMajorIterate
  534.     add si, ydiff
  535.     rol al, 1
  536.     adc bx, 0
  537. LRYMajorIterate:
  538.     out dx, al
  539.     mov es:[bx], ah
  540.     sub cx, 1
  541.     jg LRYMajorLoop
  542.     retn
  543.  
  544.  
  545. ; This is the actual starting point.
  546. ; On entry, registers look like this:
  547. ; X1: cx
  548. ; Y1: ax
  549. ; X2: di
  550. ; Y2: si
  551. ShortLine:
  552.     sub si, ax          ; height goes out in si
  553.     sub di, cx          ; width goes out in di
  554.  
  555.     mul [_ScrnLogicalByteWidth]
  556.     mov dx, cx
  557.     shr dx, 2
  558.     add ax, dx
  559.     add ax, AdjustedOffs
  560.     mov bx, ax          ; starting byte of X1, Y1 goes out in bx
  561.     and cx, 3
  562.     mov ax, 011h
  563.     shl al, cl          ; column mask goes out in al
  564.     mov dx, SC_INDEX + 1
  565.     mov ah, byte ptr Colort; color goes out in ah
  566.     out dx, al
  567.     mov es:[bx], ah     ; plot first point
  568.  
  569.     cmp di, 0
  570.  
  571.     jg LeftToRight
  572.     je VerticalLine
  573.  
  574.  
  575. RightToLeft:
  576.     neg di              ; much more useful this way
  577.     mov xdiff, di
  578.  
  579.     mov cx, [_ScrnLogicalByteWidth]
  580.     cmp si, 0           ; check if height is positive, negative, or zero
  581.     je RLHorz
  582.     jg RLTopToBottom
  583.     neg si
  584.     neg cx
  585. RLTopToBottom:
  586.     mov ydiff, si
  587.     mov moveline, cx
  588.     cmp di, si
  589.     jg RLXMajor
  590.     je RL45Deg
  591.  
  592.  
  593. RLYMajor:
  594.     mov cx, si
  595.     dec cx
  596.     shr si, 1
  597. RLYMajorLoop:
  598.     add bx, moveline
  599.     sub si, di
  600.     jge RLYMajorIterate
  601.     add si, ydiff
  602.     ror al, 1
  603.     sbb bx, 0
  604. RLYMajorIterate:
  605.     out dx, al
  606.     mov es:[bx], ah
  607.     sub cx, 1
  608.     jg RLYMajorLoop
  609.     retn
  610.  
  611.  
  612. VerticalLine:
  613.     mov cx, [_ScrnLogicalByteWidth]
  614.     cmp si, 0           ; check if height is positive
  615.     jg VTopToBottom
  616.     neg si
  617.     neg cx
  618. VTopToBottom:
  619.     dec si
  620. VLoop:
  621.     add bx, cx
  622.     mov es:[bx], ah
  623.     sub si, 1
  624.     jg VLoop
  625.     retn
  626.  
  627.  
  628. RLHorz:
  629.     dec di
  630. RLHorzLoop:
  631.     ror al, 1
  632.     sbb bx, 0
  633.     out dx, al
  634.     mov es:[bx], ah
  635.     sub di, 1
  636.     jg RLHorzLoop
  637.     retn
  638.  
  639.  
  640. RL45Deg:
  641.     dec si
  642. RL45DegLoop:
  643.     add bx, cx
  644.     ror al, 1
  645.     sbb bx, 0
  646.     out dx, al
  647.     mov es:[bx], ah
  648.     sub si, 1
  649.     jg RL45DegLoop
  650.     retn
  651.  
  652.  
  653. RLXMajor:
  654.     mov cx, di
  655.     dec cx
  656.     shr di, 1
  657. RLXMajorLoop:
  658.     sub di, si
  659.     jge RLXMajorIterate
  660.     add di, xdiff
  661.     add bx, moveline
  662. RLXMajorIterate:
  663.     ror al, 1
  664.     sbb bx, 0
  665.     out dx, al
  666.     mov es:[bx], ah
  667.     sub cx,1
  668.     jg RLXMajorLoop
  669.     retn
  670.  
  671.  
  672. _x_bezier endp
  673.  
  674.     end
  675.  
  676.